<?php

namespace app\live\controller;


use app\common\lib\exception\ApiException;
use app\common\lib\IAuth;
use think\Controller;
use think\Log;

class Common extends Controller
{

    protected $headers = [];
    protected $clientUserType = 'live';   // 调用端类型 live=>主播端 zhunle=>APP用户端 admin=>后台

    public function _initialize()
    {
        parent::_initialize();
        $this->checkRequestAuth();
    }

    /**
     * 检查每次app请求的数据是否合法
     * @throws ApiException
     */
    public function checkRequestAuth()
    {
        // 首先需要获取headers
        $headers = request()->header();
        if (!defined('IS_ACCESS_TOKEN_CHECKED'))
        {
            // 基础参数校验
            if (isset($headers['app-type']))
            {
                if (strpos(config('live_app.app_types'), $headers['app-type']) !== false || strpos(config('app.app_types'), $headers['app-type']) !== false)
                {   // APP
                    if (!isset($headers['sign']))
                    {
                        Log::write('请求缺少sign', 'error', true);
                        throw new ApiException('接口请求失败');
                    }
                    // 需要sign
                    if (!$this->checkSignPass($headers))    // 主播端验签
                    { // 主播端验签失败  尝试使用APP端验签
                        if (IAuth::checkSignPass($headers))    // APP端验签
                        {   // APP端也验签成功
                            $this->clientUserType = 'zhunle';
                        } else
                        {
                            // 如果其他端也验签失败 则抛出异常
                            Log::write('sign验签失败', 'error', true);
                            throw new ApiException('接口请求失败');
                        }
                    }
                } elseif ($headers['app-type'] === 'live_admin')
                {
                    $this->clientUserType = 'admin';
                } else
                {
                    Log::write('当前设备不支持', 'error', true);
                    throw new ApiException('当前设备不支持');
                }
            } else
            {
                Log::write('当前设备不支持', 'error', true);
                throw new ApiException('当前设备不支持');
            }

            // 1、文件  2、mysql 3、redis   由于服务器为集群架构   此处使用redis
            define('IS_ACCESS_TOKEN_CHECKED', true);
        }
        // 将当前请求头信息存入header属性中，以便后面使用
        $this->headers = $headers;
    }

    public function checkSignPass($data = [])
    {
        $str = $this->decryptWithOpenssl($data['sign']);

        if (empty($str)) return false;

        parse_str($str, $arr);

        // 临时更换 did验证
        if (!isset($arr['version'], $arr['did']) || !is_array($arr) || $arr['version'] !== $data['version'] || $arr['did'] !== $data['did'])
        {
            return false;
        }

        return true;
    }

    /**
     * 加密字符串
     * @param string $data 字符串
     * @return string
     */
    protected function encryptWithOpenssl($data): string
    {
        try
        {
            $config = config('live_app');
            return base64_encode(openssl_encrypt($data, $config['aes_method'], $config['aes_key'], OPENSSL_RAW_DATA, $config['aes_iv']));
        }
        catch (\Exception $e)
        {
            return '';
        }

    }

    /**
     * 解密字符串
     * @param string $data 字符串
     * @return string
     */
    protected function decryptWithOpenssl($data): string
    {
        try
        {
            $config = config('live_app');
            return openssl_decrypt(base64_decode($data), $config['aes_method'], $config['aes_key'], OPENSSL_RAW_DATA, $config['aes_iv']);
        }
        catch (\Exception $e)
        {
            return '';
        }
    }
}
